package com.lyhcc.utils;

import java.util.Stack;

public class StackCal {
    private final static char[][] opCmpArray = {
            {'>','>','<','<','<','>','>'},
            {'>','>','<','<','<','>','>'},
            {'>','>','>','>','<','>','>'},
            {'>','>','>','>','<','>','>'},
            {'<','<','<','<','<','=','E'},
            {'>','>','>','>','E','>','>'},
            {'<','<','<','<','<','E','='}
    };
    private static Stack<Character> optr;
    private static Stack<Fraction> opnd;

    /**
     *计酸算式
     * @param    formular   算式
     * @return      返回值为算式的结果
     */
    public static Fraction evaluateFormular(String formular){

        formular = formular.replace('=','#');

        optr = new Stack<>();       //  初始化运算符栈
        opnd = new Stack<>();       //  初始化操作数栈

        optr.push('#');



        int index = 0;
        char ch = formular.charAt(index);
        int formularLen = formular.length();//8
        while(ch != '#' || optr.peek() != '#' ){

            if(isOperand(ch)){


                StringBuffer operand = new StringBuffer();


                operand.append(formular.charAt(index));



                while(isOperand(ch)){

                    operand.append(ch);
                    ch = formular.charAt(++index);
                }

                String[] strings = operand.toString().split("/");


                if(strings.length == 1&&!"".equals(strings[0])){
                    int tmp = Integer.parseInt(strings[0]);
                    opnd.push(new Fraction(tmp,1));
                }else if(strings.length == 2){
                    opnd.push(new Fraction(Integer.parseInt(strings[0]),Integer.parseInt(strings[1])));
                }


            }else {

                switch (precede(optr.peek(),ch)){
                    case '<':
                        optr.push(ch);
                        ch = formular.charAt(++index);
                        break;
                    case '>':
                        char theta = optr.pop();
                        Fraction b = opnd.pop();
                        Fraction a = opnd.pop();
                        opnd.push(Calculator.cal(a,b,theta));

                        break;
                    case '=':
                        optr.pop();
                        ch = formular.charAt(++index);
                        break;
                }
            }
        }


        return opnd.peek();
    }

    /**
     * 比较量符号的优先级
     * @return
     */
    private static char precede(char first,char second){
        return opCmpArray[getPos(first)][getPos(second)];
    }

    /**
     * 查找某个运算符在+ - * / ( ) # 的位置
     * @param x
     * @return
     */
    private static int getPos(char x){
        switch (x){
            case '+':return 0;
            case '-':return 1;
            case '×':return 2;
            case '÷':return 3;
            case '(':return 4;
            case ')':return 5;
            case '#':return 6;
        }
        return -1;
    }
    /**
     * 判断是否为操作数
     *
     * @return 如果是操作数，则返回true，否则返回false
     */
    private static boolean isOperand(char ch) {
        return ch != '+'&& ch != '-' && ch != '×'&&ch != '÷'
                && ch != '#'&&ch != '('&&ch != ')';
    }
}
